﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.Linq;

namespace Dycox.ComponentModel
{
    [Obsolete("This class is subject to remove later.")]
    public static class ModelManager
    {
        public static readonly XNamespace ModelNamespace = "urn:effun-net-dycox-data-model";
        public static readonly XNamespace ViewNamespace = "urn:effun-net-data-view";

        static Dictionary<Type, ModelSchema> _models;
        static Dictionary<string, ModelView> _views;

        static ModelManager()
        {
            _models = new Dictionary<Type, ModelSchema>();
            _views = new Dictionary<string, ModelView>();
        }

        public static ModelSchema GetModel(Type type)
        {
            if (type == null)
                throw new ArgumentNullException("type");

            ModelSchema model;

            if (_models.TryGetValue(type, out model))
                return model;

            LoadModels(type);

            if (_models.TryGetValue(type, out model))
                return model;

            throw new ArgumentException("Model settigns of " + type.FullName + " is not defined.");
        }

        private static void LoadModels(Type type)
        {
            foreach (string name in type.Assembly.GetManifestResourceNames())
            {
                if (name.EndsWith("models.xml", StringComparison.InvariantCultureIgnoreCase))
                {
                    using (Stream stream = type.Assembly.GetManifestResourceStream(name))
                    {
                        LoadModels(stream);
                    }
                }
            }
        }

        private static void LoadModels(Stream stream)
        {

            lock (_models)
            {
                XDocument doc = XDocument.Load(stream);
                List<ModelSchema> list = new List<ModelSchema>();

                foreach (XElement eltModel in doc.Root.Elements(ModelNamespace + "model"))
                {
                    ModelSchema settings = new ModelSchema(eltModel);

                    //if (!settings.Typeless)
                    {
                        if (_models.ContainsKey(settings.ModelType))
                            throw new InvalidOperationException("Model " + settings.ModelType.FullName + " has already been defined.");

                        list.Add(settings);
                    }
                }

                foreach (ModelSchema ms in list)
                    _models.Add(ms.ModelType, ms);
            }
        }

        public static ModelView LoadView(Type type)
        {
            string name = type.FullName;
            name += ".View.xml";
            return LoadView(type.Assembly, name);
        }

        public static ModelView LoadView(System.Reflection.Assembly assembly, string resName)
        {
            ModelView vs;

            resName = assembly.GetManifestResourceNames().SingleOrDefault(o => string.Compare(o, resName, true) == 0);

            if (resName == null)
                return null;

            if (!_views.TryGetValue(resName, out vs))
            {
                Stream stream;


                stream = assembly.GetManifestResourceStream(resName);
                using (stream)
                {
                    vs = LoadView(stream);
                }

                _views.Add(resName, vs);
            }

            return vs;
        }

        private static ModelView LoadView(Stream input)
        {
            throw new InvalidOperationException();
        }
    }
}
